﻿using FluentValidation;
using Nop.Core.Domain.Common;
using Nop.Services.Localization;
using Nop.Services.Logistics;
using Nop.Web.Models.Common;

namespace Nop.Web.Validators.Common
{
    public class AddressValidator : AbstractValidator<AddressModel>
    {
        public AddressValidator(ILocalizationService localizationService, AddressSettings addressSettings, ILogisticsService logisticsService)
        {
            const string phoneRegex = @"^[\\(]{0,1}([0-9]){3}[\\)]{0,1}[{ ,\-,.}]?([^0-1]){1}([0-9]){2}[{ ,\-,.}]?([0-9]){4}[ ]*((x|X){0,1}([0-9]){1,5}){0,1}$";
            RuleFor(x => x.FirstName)
                .NotEmpty()
                .WithMessage(localizationService.GetResource("Address.Fields.FirstName.Required"));
            RuleFor(x => x.LastName)
                .NotEmpty()
                .WithMessage(localizationService.GetResource("Address.Fields.LastName.Required"));
            RuleFor(x => x.Email)
             .NotEmpty()
             .WithMessage(localizationService.GetResource("Address.Fields.Email.Required"));
            //RuleFor(x => x.Email)
            //   .NotEmpty()
            //   .Unless(x => x.AllowEmpty || x.AllowEmailEmpty)
            //   .WithMessage(localizationService.GetResource("Address.Fields.Email.Required"));
            RuleFor(x => x.Email)
                .EmailAddress()
                .WithMessage(localizationService.GetResource("Common.WrongEmail"))
               .When(x => !string.IsNullOrEmpty(x.Email));
            if (addressSettings.CountryEnabled)
            {
                RuleFor(x => x.CountryId)
                    .NotNull()
                    .WithMessage(localizationService.GetResource("Address.Fields.Country.Required"));
                RuleFor(x => x.CountryId)
                    .NotEqual(0)
                    .WithMessage(localizationService.GetResource("Address.Fields.Country.Required"));
            }
            if (addressSettings.StateProvinceEnabled)
            {
                RuleFor(x => x.StateProvinceId)
                    .NotNull()
                    .NotEqual(0)
                    .WithMessage(localizationService.GetResource("Address.Fields.StateProvince.Required"));
            }

            if (addressSettings.CompanyRequired && addressSettings.CompanyEnabled)
            {
                RuleFor(x => x.Company).NotEmpty().WithMessage(localizationService.GetResource("Account.Fields.Company.Required"));
            }
            if (addressSettings.StreetAddressRequired && addressSettings.StreetAddressEnabled)
            {
                RuleFor(x => x.Address1).NotEmpty().WithMessage(localizationService.GetResource("Account.Fields.StreetAddress.Required"));
            }
            if (addressSettings.StreetAddress2Required && addressSettings.StreetAddress2Enabled)
            {
                RuleFor(x => x.Address2).NotEmpty().WithMessage(localizationService.GetResource("Account.Fields.StreetAddress2.Required"));
            }
            if (addressSettings.ZipPostalCodeRequired && addressSettings.ZipPostalCodeEnabled)
            {
                RuleFor(x => x.ZipPostalCode).NotEmpty().WithMessage(localizationService.GetResource("Account.Fields.ZipPostalCode.Required"));
            }
            if (addressSettings.ZipPostalCodeRequired && addressSettings.ZipPostalCodeEnabled)
            {
                RuleFor(x => x.ZipPostalCode)
                .Cascade(FluentValidation.CascadeMode.StopOnFirstFailure)
                .Matches(@"^ *[ABCEGHJKLMNPRSTVXYabceghjklmnprstvxy]{1}\d{1}[A-Za-z]{1} *\d{1}[A-Za-z]{1}\d{1} *$")
                .Unless(x => x.Address1 != null && x.Address1.Contains("10 Glenlake Parkway")) // Hard-coded backdoor for testing.
                .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.Invalid"))
                .Must(zp => (logisticsService.GetDistrictByZipPostalCode(zp) != null))
                .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.NoService"))
                .Must((x, zp) =>
                    (!x.StateProvinceId.HasValue ||
                    x.StateProvinceId.Value == 0 ||
                    x.StateProvinceId.Value == logisticsService.GetDistrictByZipPostalCode(zp).StateProvinceId))
                .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.NotInStateProvince"));
            }
            //if (addressSettings.ZipPostalCodeRequired && addressSettings.ZipPostalCodeEnabled)
            //{
            //    RuleFor(x => x.ZipPostalCode)
            //        .Cascade(FluentValidation.CascadeMode.StopOnFirstFailure)
            //        .Matches(@"^ *[ABCEGHJKLMNPRSTVXYabceghjklmnprstvxy]{1}\d{1}[A-Za-z]{1} *\d{1}[A-Za-z]{1}\d{1} *$")
            //        .Unless(x => x.Address1 != null && x.Address1.Contains("10 Glenlake Parkway")) // Hard-coded backdoor for testing.
            //        .WithMessage(localizationService.GetResource("Address.Fields.Zippostalcode.Invalid"));
            //}
            if (addressSettings.CityRequired && addressSettings.CityEnabled)
            {
                RuleFor(x => x.City).NotEmpty().WithMessage(localizationService.GetResource("Address.Fields.City.Required"));
            }
            if (addressSettings.PhoneRequired && addressSettings.PhoneEnabled)
            {
                RuleFor(x => x.PhoneNumber).NotEmpty().WithMessage(localizationService.GetResource("Address.Fields.Phone.Required"));
            }
            if (addressSettings.PhoneRequired && addressSettings.PhoneEnabled)
            {
                RuleFor(x => x.PhoneNumber)
                    .Matches(phoneRegex)
                    .WithMessage(localizationService.GetResource("Address.Fields.Phone.Invalid"));
            }
            if (addressSettings.CellPhoneRequired && addressSettings.CellPhoneEnabled)
            {
                RuleFor(x => x.CellPhoneNumber).NotEmpty().WithMessage(localizationService.GetResource("Address.Fields.Cellphonenumber.Required"));
            }
            if (addressSettings.CellPhoneRequired && addressSettings.CellPhoneEnabled)
            {
                RuleFor(x => x.CellPhoneNumber)
                    .Matches(phoneRegex)
                    .WithMessage(localizationService.GetResource("Address.Fields.Cellphonenumber.Invalid"));
            }
            if (addressSettings.FaxRequired && addressSettings.FaxEnabled)
            {
                RuleFor(x => x.FaxNumber).NotEmpty().WithMessage(localizationService.GetResource("Account.Fields.Fax.Required"));
            }
        }
    }
}